﻿using ArivisTests.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

namespace ArivisTests.Views
{
    public class CheckboxItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public static class Helpers
    {
        private static System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"(#|ticket:)(\d+)");

        public static MvcHtmlString TestProgressText(this HtmlHelper helper, IEnumerable<TestCase> tests, bool progressbar = true)
        {
            StringBuilder sb = new StringBuilder();
            var remaining = tests.Where(x => x.Result == null);
            var remainingCount = remaining.Count();
            int totalCount = tests.Count();
            int duration = remaining.Sum(x => x.Scenario.Duration);
            int progress = (totalCount == 0) ? 0 : ((totalCount-remainingCount) * 100 / totalCount);

            string durationString = FormatMinutes(helper, duration).ToHtmlString();

            sb.AppendFormat("<strong>{0}</strong> tests done, ", totalCount - remainingCount);
            sb.AppendFormat("<strong>{0}</strong> tests with <strong>{1}</strong> remaining", remainingCount, durationString);
            if (progressbar && totalCount > 0)
            {
                sb.AppendLine("<table class=\"progress-bar\"><tr>");
                foreach(var group in tests.GroupBy(x => x.Result).OrderByDescending(x => x.Key))
                {
                    var groupCount = group.Count();
                    int percent = groupCount * 100 / totalCount;
                    string color = (group.Key == null) ? "white" : group.Key.Color;
                    string title = (group.Key == null) ? "No Result" : group.Key.Name;
                    sb.AppendFormat("<td title=\"{0}: {3}/{4}, {1}%\" style=\"width:{1}%;background-color:{2};\"></td>", title, percent, color, groupCount, totalCount);
                }
                sb.AppendLine("</tr></table>");
            }


            return MvcHtmlString.Create(sb.ToString());
        }

        public static MvcHtmlString FormatMinutes(this HtmlHelper helper, int minutes)
        {
            if (minutes <= 60)
            {
                return MvcHtmlString.Create(minutes + "min");
            }

            int hours = (minutes / 60);
            minutes = minutes % 60;
            if (minutes > 0)
            {
                return MvcHtmlString.Create(hours + "h " + (minutes % 60) + "min");
            }
            else
            {
                return MvcHtmlString.Create(hours + "h ");
            }

        }

        public static MvcHtmlString DisplayTickets(this HtmlHelper helper, string ticketUrl, string tickets)
        {
            if (string.IsNullOrWhiteSpace(tickets))
                return MvcHtmlString.Empty;
            string urlformat = "<a target=\"_blank\" href='" + ticketUrl + "$2'>$1$2</a>";
            string result = regex.Replace(tickets, urlformat);
            return MvcHtmlString.Create(result);
        }

        public static MvcHtmlString Checkboxes(this HtmlHelper helper, string name, IEnumerable<SelectListItem> items)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in items)
            {
                string isChecked = item.Selected ? "checked=\"checked\"" : string.Empty;
                sb.AppendFormat("<input type=\"checkbox\" name=\"{0}\" value=\"{1}\" {3}/>&nbsp;{2} ", name, item.Value, item.Text, isChecked);
            }
            return MvcHtmlString.Create(sb.ToString());
        }

        public static MvcHtmlString CheckboxList(this HtmlHelper helper, string name, IEnumerable<TestItem> items)
        {
            return CheckboxList(helper, name, items, item => false);
        }


        public static MvcHtmlString CheckboxList(this HtmlHelper helper, string name, IEnumerable<TestItem> items, Func<TestItem, bool> isChecked)
        {
            if (items == null || items.Any() == false)
            {
                return MvcHtmlString.Empty;
            }
            StringBuilder sb = new StringBuilder();
            sb.Append("<div class=\"checkbox-list-actions\">");
            string script = "<a href=\"\" onclick=\"jQuery(this).parent().parent().find('input').attr('checked', {0}); return false;\">{1}</a>";
            sb.AppendFormat(script, "true", "Select All");
            sb.Append(" | ");
            sb.AppendFormat(script, "false", "Clear Selection");
            sb.AppendLine("</div>");
            sb.AppendLine("<div class=\"checkbox-list-overflow\">");
            sb.AppendLine("<table class=\"checkbox-list\">");
            foreach (var item in items)
            {
                string checkedValue = isChecked(item) ? "checked=\"checked\"" : string.Empty;
                sb.AppendFormat("<tr><td><input type=\"checkbox\" name=\"{0}\" value=\"{1}\" {3}/></td><td>{2}</td></tr>\n", name, item.Id, item.Name, checkedValue);
            }
            sb.AppendLine("</table>");
            sb.AppendLine("</div>");
            return MvcHtmlString.Create(sb.ToString());
        }


        public static MvcHtmlString LinkedItems(this HtmlHelper helper, IEnumerable<TestScenario> items)
        {
            return LinkedItems(helper, "Details", "TestScenario", items, false);
        }

        public static MvcHtmlString LinkedItems(this HtmlHelper helper, IEnumerable<TestCase> items)
        {
            return LinkedItems(helper, "Details", "TestCase", items, false);
        }


        public static MvcHtmlString LinkedItems(this HtmlHelper helper, IEnumerable<TestPlan> items)
        {
            return LinkedItems(helper, "Details", "TestPlan", items, false);
        }


        public static MvcHtmlString LinkedItems(this HtmlHelper helper, string action, string controller, IEnumerable<TestItem> items)
        {
            return LinkedItems(helper, action, controller, items, false);
        }

        public static MvcHtmlString LinkedItems(this HtmlHelper helper, string action, string controller, IEnumerable<TestItem> items, bool asList)
        {
            if (items == null || items.Any() == false)
            {
                return MvcHtmlString.Empty;
            }
            string separator = asList ? "<br />" : "; ";

            StringBuilder sb = new StringBuilder();
            bool first = true;
            foreach (var item in items)
            {
                if (first) { first = false; } else { sb.Append(separator); }
                sb.Append(helper.ActionLink(item.Name, action, controller, new { id = item.Id }, null).ToHtmlString());
            }
            return MvcHtmlString.Create(sb.ToString());
        }

        public static MvcHtmlString UserDropDownList(this HtmlHelper helper, string name, IEnumerable<UserProfile> profiles)
        {
            var items = profiles.Select( x => ToSelectListItem(x, false));
            return helper.DropDownList(name, items, string.Empty);
        }

        public static MvcHtmlString UserDropDownList(this HtmlHelper helper, string name, IEnumerable<UserProfile> profiles, UserProfile selected)
        {
            var items = profiles.Select(x => ToSelectListItem(x, x.Equals(selected)));
            return helper.DropDownList(name, items, string.Empty);
        }

        public static MvcHtmlString TestItemDropDownList<T>(this HtmlHelper helper, string name, IEnumerable<T> items) where T : TestItem
        {
            var selectListItems = items.Select( x => TestItemToSelectItem(x, false));
            return helper.DropDownList(name, selectListItems, string.Empty);
        }

        public static MvcHtmlString TestItemDropDownList<T>(this HtmlHelper helper, string name, IEnumerable<T> items, T selected) where T : TestItem
        {
            var selectListItems = items.Select( x => TestItemToSelectItem(x, x.Equals(selected)));
            return helper.DropDownList(name, selectListItems, string.Empty);
        }

        public static MvcHtmlString Paging<T>(this HtmlHelper helper, ICollection<T> model, int pageSize, string actionName, RouteValueDictionary routeValues)
        {
            return Helpers.Paging(helper, model.Count(), pageSize, actionName, routeValues);
        }

        public static MvcHtmlString Paging(this HtmlHelper helper, int itemCount, int pageSize, string actionName, RouteValueDictionary routeValues)
        {
            int pageCount = itemCount / pageSize;
            if (itemCount % pageSize > 0) pageCount++;

            int activePage = 0;
            Int32.TryParse(helper.ViewContext.HttpContext.Request["page"], out activePage);

            if (pageCount<2){
                return MvcHtmlString.Empty;
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<table class=\"paging\"><tr>");


            for (int page = 0; page < pageCount; page++)
            {
                int from = page*pageSize + 1;
                int to = Math.Min((page + 1) * pageSize, itemCount);
                if (page == activePage)
                {
                    sb.AppendFormat("<td><strong>{0}-{1}</strong></td>", from, to);
                }
                else
                {
                    string text = string.Format("{0}-{1}", from, to);
                    routeValues["page"] = page;
                    sb.Append("<td>");
                    sb.Append(helper.ActionLink(text, actionName, routeValues).ToHtmlString());
                    sb.Append("</td>");
                }
            }

            sb.AppendLine("</tr></table>");
            return MvcHtmlString.Create(sb.ToString());
        }

        private static SelectListItem ToSelectListItem(UserProfile profile, bool selected)
        {
            return new SelectListItem() { Value = profile.UserId.ToString(), Text = profile.UserName, Selected = selected };
        }

        private static SelectListItem TestItemToSelectItem(TestItem testItem, bool selected)
        {
            return new SelectListItem() { Value = testItem.Id.ToString(), Text = testItem.Name, Selected = selected };
        }
    }
}